home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 051-075 / disk_051 / sq.usq / sq.c < prev    next >
C/C++ Source or Header  |  1992-05-06  |  6KB  |  229 lines

  1. /* This program compresses a file without losing information.
  2.  * The "usq" program is required to unsqueeze the file
  3.  * before it can be used.
  4.  *
  5.  * Typical compression rates are between 30 and 50 percent for text files.
  6.  *
  7.  * Squeezing a really big file takes a few minutes.
  8.  *
  9.  * Useage:
  10.  *    sq [file1] [file2] ... [filen]
  11.  *
  12.  * where file1 through filen are the names of the files to be squeezed.
  13.  * The file type (under CP/M or MS-DOS) is changed to ".SQ"; under UN*X,
  14.  * ".SQ" is appended to the file name. The original file name is stored
  15.  * in the squeezed file.
  16.  *
  17.  * If no file name is given on the command line you will be
  18.  * prompted for commands (one at a time). An empty command
  19.  * terminates the program.
  20.  *
  21.  * The transformations compress strings of identical bytes and
  22.  * then encode each resulting byte value and EOF as bit strings
  23.  * having lengths in inverse proportion to their frequency of
  24.  * occurrance in the intermediate input stream. The latter uses
  25.  * the Huffman algorithm. Decoding information is included in
  26.  * the squeezed file, so squeezing short files or files with
  27.  * uniformly distributed byte values will actually increase size.
  28.  */
  29.  
  30. /* CHANGE HISTORY:
  31.  * 1.3    Close files properly in case of error exit.
  32.  * 1.4    Break up long introductory lines.
  33.  * 1.4    Send introduction only to console.
  34.  * 1.4    Send errors only to console.
  35.  * 1.5  Fix BUG that caused a rare few squeezed files
  36.  *    to be incorrect and fail the USQ crc check.
  37.  *    The problem was that some 17 bit codes were
  38.  *    generated but are not supported by other code.
  39.  *    THIS IS A MAJOR CHANGE affecting TR2.C and SQ.H and
  40.  *    requires recompilation of all files which are part
  41.  *    of SQ. Two basic changes were made: tree depth is now
  42.  *    used as a tie breaker when weights are equal. This
  43.  *    makes the tree shallower. Although that may always be
  44.  *    sufficient, an error trap was added to cause rescaling
  45.  *    of the counts if any code > 16 bits long is generated.
  46.  * 1.5    Add debugging displays option '-'.
  47.  * 1.6  Fixed to work correctly under MP/M II.  Also shortened
  48.  *      signon message.
  49.  * 2.0    New version for use with CI-C86 compiler (CP/M-86 and MS-DOS)
  50.  * 2.1  Converted for use in MLINK
  51.  * 2.2  Converted for use with optimizing CI-C86 compiler (MS-DOS)
  52.  * 3.0  Generalized for UN*X use, changed output file naming convention
  53.  * 3.3  Modified to work with ULTRIX, as per Tom Reid.
  54.  */
  55.  
  56. /* eject eject */
  57.  
  58. /*
  59.  * The following define MUST be set to the maximum length of a file name
  60.  * on the system "sq" is being compiled for.  If not, "sq" will not be
  61.  * able to check for whether the output file name it creates is valid
  62.  * or not.
  63.  */
  64.  
  65. #ifdef AMIGA
  66. #define FNM_LEN 30
  67. #else
  68. #define FNM_LEN 14
  69. #endif
  70.  
  71. /*#define UNIX             comment out for CP/M, MS-DOS versions */
  72. /*#define ULTRIX         comment out for non-ULTRIX versions */
  73. #define SQMAIN
  74.  
  75. #ifdef UNIX
  76. #define NO_EXTENSIONS
  77. #endif
  78.  
  79. #ifdef AMIGA
  80. #define NO_EXTENSIONS
  81. #endif
  82.  
  83. #define VERSION "3.3   10/29/86"
  84.  
  85. #include <stdio.h>
  86. #include "sqcom.h"
  87. #include "sq.h"
  88. #define FALSE 0
  89.  
  90. main(argc, argv)
  91. int argc;
  92. char *argv[];
  93. {
  94.     int i,c;
  95.     char inparg[128];    /* parameter from input */
  96.  
  97.     debug = FALSE;
  98.     printf("File squeezer version %s (original author: R. Greenlaw)\n\n", VERSION);
  99.  
  100.     /* Process the parameters in order */
  101.     for(i = 1; i < argc; ++i)
  102.         obey(argv[i]);
  103.  
  104.     if(argc < 2) {
  105.         printf("Enter file names, one line at a time, or type <RETURN> to quit.");
  106.         do {
  107.             printf("\n*");
  108.             for(i = 0; i < 16; ++i) {
  109.                 if((c = getchar()) == EOF)
  110.                     c = '\n';    /* fake empty (exit) command */
  111.                 if((inparg[i] = c) == '\n') {
  112.                     inparg[i] = '\0';
  113.                     break;
  114.                 }
  115.             }
  116.             if(inparg[0] != '\0')
  117.                 obey(inparg);
  118.         } while(inparg[0] != '\0');
  119.     }
  120. }
  121.  
  122. /* eject eject */
  123.  
  124. obey(p)
  125. char *p;
  126. {
  127.     char *q;
  128.     char outfile[128];    /* output file spec. */
  129.  
  130.     if(*p == '-') {
  131.         /* toggle debug option */
  132.         debug = !debug;
  133.         return;
  134.     }
  135.  
  136.     /* Check for ambiguous (wild-card) name */
  137.     for(q = p; *q != '\0'; ++q)
  138.         if(*q == '*' || *q == '?') {
  139.             printf("\nAmbiguous name %s ignored", p);
  140.             return;
  141.     }
  142.     /* First build output file name */
  143.     strcpy(outfile, p);        /* copy input name to output */
  144.  
  145.     /* Find and change output file suffix */
  146.  
  147.     if (strlen(outfile) + 3 > FNM_LEN) {    /* check for long file name */
  148.         q = outfile + FNM_LEN - 3;
  149.         *q = '\0';        /* make room for suffix */
  150.     }
  151.     else {
  152.         q = outfile + strlen(outfile);
  153. #ifdef NO_EXTENSIONS
  154.         for(; --q >= outfile;)
  155.             if (*q == '.') {
  156.                 *q = '\0';    /* delete file type */
  157.                 break;
  158.             }
  159. #else
  160.         --q;
  161. #endif
  162.     }
  163.  
  164.     strcat(outfile, ".SQ");
  165.  
  166.     squeeze(p, outfile);
  167. }
  168.  
  169. /* eject eject */
  170.  
  171. squeeze(infile, outfile)
  172. char *infile, *outfile;
  173. {
  174.     int i, c,c2;
  175.     FILE *inbuff, *outbuff;        /* file buffers */
  176.  
  177.     printf("%s -> %s: ", infile, outfile);
  178.  
  179. #if ULTRIX || AMIGA
  180.     if(!(inbuff=fopen(infile, "r"))) {
  181. #else
  182.     if(!(inbuff=fopen(infile, "rb"))) {
  183. #endif
  184.         printf("Can't open %s for input pass 1\n", infile);
  185.         return;
  186.     }
  187. #if ULTRIX || AMIGA
  188.     if(!(outbuff=fopen(outfile, "w"))) {
  189. #else
  190.     if(!(outbuff=fopen(outfile, "wb"))) {
  191. #endif
  192.         printf("Can't create %s\n", outfile);
  193.         fclose(inbuff);
  194.         return;
  195.     }
  196.  
  197.     /* First pass - get properties of file */
  198.     crc = 0;    /* initialize checksum */
  199.     printf("analyzing, ");
  200.     init_ncr();
  201.     init_huff(inbuff);   
  202.     fclose(inbuff);
  203.  
  204.     /* Write output file header with decoding info */
  205.     wrt_head(outbuff, infile);
  206.  
  207.     /* Second pass - encode the file */
  208.     printf("squeezing,");
  209. #if ULTRIX || AMIGA
  210.     if(!(inbuff=fopen(infile, "r"))) {
  211. #else
  212.     if(!(inbuff=fopen(infile, "rb"))) {
  213. #endif
  214.         printf("Can't open %s for input pass 2\n", infile);
  215.         goto closeout;
  216.     }
  217.     init_ncr();    /* For second pass */
  218.  
  219.     /* Translate the input file into the output file */
  220.     while((c = gethuff(inbuff)) != EOF)
  221.         putce(c, outbuff);
  222.     oflush(outbuff);
  223.     printf(" done.\n");
  224. closeall:
  225.     fclose(inbuff);
  226. closeout:
  227.     fclose(outbuff);
  228. }
  229.